package ${projectDomain}.core;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiConstructor;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;
import com.unswift.cache.MemoryCache;
import ${projectDomain}.cache.ICacheAdapter;
import ${projectDomain}.cache.RedisAdapter;
import ${projectDomain}.config.TokenConfig;
import ${projectDomain}.core.entity.TokenUser;
import ${projectDomain}.pojo.vo.page.IPageVo;
import ${projectDomain}.utils.HttpUtils;
import ${projectDomain}.utils.ServletUtils;
import com.unswift.utils.ClassUtils;
import com.unswift.utils.ExceptionUtils;
import com.unswift.utils.ObjectUtils;

@Api(value="公共组件类，如：获取用户信息", author="unswift", date="2023-06-01", version="1.0.0")
public abstract class CommonOperator {

	@ApiField("日志对象")
	protected final Logger logger=LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	@ApiField("token的yml配置")
	protected TokenConfig tokenConfig;
	
	@Autowired
	@ApiField("http请求公共对象")
	protected HttpUtils httpUtils;
	
	@Lazy
	@Autowired
	@ApiField("业务缓存Service，懒加载")
	protected ICacheAdapter cacheAdapter;
	
	@Autowired
	@ApiField("redis缓存service")
	protected RedisAdapter redisAdapter;
	
	@Autowired
	@ApiField("内存缓存service")
	protected MemoryCache memoryCache;
	
	@ApiMethod(value="获取登录会员", returns=@ApiField("登录会员信息"))
	public TokenUser getUser(){
		String token=ServletUtils.getHeader(tokenConfig.getKeyName());
		return getUser(token);
	}
	
	@ApiMethod(value="获取登录会员", returns=@ApiField("登录会员信息"))
	public TokenUser getUser(String token){
		if(ObjectUtils.isEmpty(token)){
			return null;
		}
		token = getUserToken(token);
		return redisAdapter.get(token);
	}
	
	@ApiMethod(value="获取登录会员Id", returns=@ApiField("登录会员信息"))
	public Long getUserId(){
		TokenUser user=getUser();
		if(ObjectUtils.isNotEmpty(user)) {
			return user.getId();
		}
		return null;
	}
	
	@ApiMethod(value="根据Token获取当前会员Id", returns=@ApiField("登录会员信息"))
	public Long getUserId(String token){
		TokenUser user=getUser(token);
		if(ObjectUtils.isNotEmpty(user)) {
			return user.getId();
		}
		return null;
	}

	@ApiMethod(value="根据header token获取用户token", params = {@ApiField("Request Headers Token")})
	public String getUserToken(String token) {
		String prefix = tokenConfig.getHeader()+" ";
		ExceptionUtils.falseException(token.startsWith(prefix), "token.format.error");//Request Token必须以指定字符开始
		return token.substring(prefix.length());
	}
	
	@ApiMethod(value="判断当前是否登录", returns=@ApiField("是否登录{true：登录，false：未登录}"))
	public boolean existsUser(){
		String token=ServletUtils.getHeader(tokenConfig.getKeyName());
		if(ObjectUtils.isEmpty(token)){
			return false;
		}
		token=getUserToken(token);
		return redisAdapter.exists(token);
	}
	
	@ApiMethod(value="转换pojo对象", params={@ApiField("源对象"), @ApiField("目标对象"), @ApiField("字段扩展处理，如：列表为不同的泛型时")}, returns=@ApiField("目标对象"))
	public <T, S> T convertPojo(S source, T target, PojoFieldExtend<?, ?>...fieldExtends){
		if(ObjectUtils.isEmpty(source)){
			return target;
		}
		ObjectUtils.copy(source, target);
		if(ObjectUtils.isNotEmpty(fieldExtends)) {
			for (PojoFieldExtend<?, ?> pojoFieldExtend : fieldExtends) {
				ClassUtils.set(target, pojoFieldExtend.fieldName, pojoFieldExtend.customAuto(ClassUtils.get(source, pojoFieldExtend.fieldName)));
			}
		}
		return target;
	}
	
	@ApiMethod(value="转换pojo对象，如果字段不一致可配置对照关系", params={@ApiField("源对象"), @ApiField("目标对象"), @ApiField("原字段"), @ApiField("对照字段")}, returns=@ApiField("目标对象"))
	public <T, S> T convertPojo(S source, T target, String[] sourceField, String[] matchField){
		if(ObjectUtils.isEmpty(source)){
			return target;
		}
		ObjectUtils.copy(source, target, sourceField, matchField);
		return target;
	}
	
	@ApiMethod(value="转换pojo对象", params={@ApiField("源对象"), @ApiField("目标对象类型"), @ApiField("字段扩展处理，如：列表为不同的泛型时")}, returns=@ApiField("目标对象"))
	public <T, S> T convertPojo(S source, Class<T> targetClass, PojoFieldExtend<?, ?>...fieldExtends){
		if(ObjectUtils.isEmpty(source)){
			return null;
		}
		T target=ClassUtils.newInstance(targetClass);
		ObjectUtils.copy(source, target);
		if(ObjectUtils.isNotEmpty(fieldExtends)) {
			for (PojoFieldExtend<?, ?> pojoFieldExtend : fieldExtends) {
				ClassUtils.set(target, pojoFieldExtend.fieldName, pojoFieldExtend.customAuto(ClassUtils.get(source, pojoFieldExtend.fieldName)));
			}
		}
		return target;
	}
	
	@Api(value="实体转换扩展")
	public static abstract class PojoFieldExtend<S, T>{
		
		@ApiField("字段名称")
		private String fieldName;
		
		@ApiConstructor(value="带参构造", params = @ApiField("字段名称"))
		public PojoFieldExtend(String fieldName) {
			this.fieldName=fieldName;
		}
		
		@ApiMethod(value="客户自定义转换实现", params = @ApiField("源字段值"), returns = @ApiField("目标字段值"))
		public abstract T customAuto(S s);
	}
	
	@ApiMethod(value="转换pojo对象，如果字段不一致可配置对照关系", params={@ApiField("源对象"), @ApiField("目标对象类型"), @ApiField("原字段"), @ApiField("对照字段")}, returns=@ApiField("目标对象"))
	public <T, S> T convertPojo(S source, Class<T> targetClass, String[] sourceField, String[] matchField){
		if(ObjectUtils.isEmpty(source)){
			return null;
		}
		T target=ClassUtils.newInstance(targetClass);
		ObjectUtils.copy(source, target, sourceField, matchField);
		return target;
	}
	
	@SuppressWarnings("unchecked")
	@ApiMethod(value="转换page对象", params={@ApiField("源page对象"), @ApiField("目标page的数据对象类型"), @ApiField("字段扩展处理，如：列表为不同的泛型时")}, returns=@ApiField("目标page"))
	public <T, S, P1 extends IPageVo<S>, P2 extends IPageVo<T>> P2 convertPage(P1 page, Class<T> targetClass, PojoFieldExtend<?, ?>...fieldExtends){
		if(ObjectUtils.isNull(page)){
			return null;
		}
		List<T> targetList=new ArrayList<T>();
		List<S> sourceList=page.getDataList();
		if(ObjectUtils.isNotEmpty(sourceList)){
			T target;
			for (S source : sourceList) {
				target=ClassUtils.newInstance(targetClass);
				ObjectUtils.copy(source, target);
				if(ObjectUtils.isNotEmpty(fieldExtends)) {
					for (PojoFieldExtend<?, ?> pojoFieldExtend : fieldExtends) {
						ClassUtils.set(target, pojoFieldExtend.fieldName, pojoFieldExtend.customAuto(ClassUtils.get(source, pojoFieldExtend.fieldName)));
					}
				}
				targetList.add(target);
			}
		}
		P2 targetPage=(P2)ClassUtils.newInstance(page.getClass());
		ObjectUtils.copy(page, targetPage);
		targetPage.setDataList(targetList);
		return targetPage;
	}
	
	@SuppressWarnings("unchecked")
	@ApiMethod(value="转换page对象，如果字段不一致可配置对照关系", params={@ApiField("源page对象"), @ApiField("目标page的数据对象类型"), @ApiField("原字段"), @ApiField("对照字段")}, returns=@ApiField("目标page"))
	public <T, S, P1 extends IPageVo<S>, P2 extends IPageVo<T>> P2 convertPage(P1 page, Class<T> targetClass, String[] sourceField, String[] matchField){
		if(ObjectUtils.isNull(page)){
			return null;
		}
		List<T> targetList=new ArrayList<T>();
		List<S> sourceList=page.getDataList();
		if(ObjectUtils.isNotEmpty(sourceList)){
			T target;
			for (S source : sourceList) {
				target=ClassUtils.newInstance(targetClass);
				ObjectUtils.copy(source, target, sourceField, matchField);
				targetList.add(target);
			}
		}
		P2 targetPage=(P2)ClassUtils.newInstance(page.getClass());
		ObjectUtils.copy(page, targetPage);
		targetPage.setDataList(targetList);
		return targetPage;
	}
	
	@ApiMethod(value="转换list对象", params={@ApiField("源list对象"), @ApiField("目标list的元素对象类型"), @ApiField("字段扩展处理，如：列表为不同的泛型时")}, returns=@ApiField("目标list"))
	public <T, S> List<T> convertPojoList(List<S> sourceList, Class<T> targetClass, PojoFieldExtend<?, ?>...fieldExtends){
		if(ObjectUtils.isNull(sourceList)){
			return null;
		}
		if(ObjectUtils.isEmpty(sourceList)){
			return new ArrayList<T>();
		}
		List<T> targetList=new ArrayList<T>();
		T target;
		for (S source : sourceList) {
			target=ClassUtils.newInstance(targetClass);
			ObjectUtils.copy(source, target);
			if(ObjectUtils.isNotEmpty(fieldExtends)) {
				for (PojoFieldExtend<?, ?> pojoFieldExtend : fieldExtends) {
					ClassUtils.set(target, pojoFieldExtend.fieldName, pojoFieldExtend.customAuto(ClassUtils.get(source, pojoFieldExtend.fieldName)));
				}
			}
			targetList.add(target);
		}
		return targetList;
	}
	
	@ApiMethod(value="转换list对象，如果字段不一致可配置对照关系", params={@ApiField("源list对象"), @ApiField("目标list的元素对象类型")}, returns=@ApiField("目标list"))
	public <T, S> List<T> convertPojoList(List<S> sourceList, Class<T> targetClass, String[] sourceField, String[] matchField){
		if(ObjectUtils.isNull(sourceList)){
			return null;
		}
		if(ObjectUtils.isEmpty(sourceList)){
			return new ArrayList<T>();
		}
		List<T> targetList=new ArrayList<T>();
		T target;
		for (S source : sourceList) {
			target=ClassUtils.newInstance(targetClass);
			ObjectUtils.copy(source, target, sourceField, matchField);
			targetList.add(target);
		}
		return targetList;
	}
	
	public String getHeader(String key) {
		return ServletUtils.getRequest().getHeader(key);
	}
	
	public String getLanguage() {
		return ServletUtils.getRequest().getHeader("Language");
	}
}
